package com.luyang.framework.ddd.ability;

import com.luyang.framework.protocol.Result;
import com.luyang.framework.protocol.ResultCode;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.Objects;

/**
 * 基础能力抽象类
 *
 * @author lu_yang
 */
@Component
public abstract class BaseAbility<T, R> {


    /**
     * 能力点执行
     *
     * @param abilityCmd abilityCmd
     * @return com.luyang.framework.protocol.Result
     * @author lu_yang
     */
    @Transactional(rollbackFor = Exception.class)
    public Result<R> executeAbility(T abilityCmd) {
        try {
            //初始化上下文
            AbilityContext.initContext();
            //能力点执行前的参数校验
            checkHandler(abilityCmd);
            //能力点执行前的幂等校验
            Result<R> checkIdempotent = checkIdempotent(abilityCmd);
            if (Objects.isNull(checkIdempotent)
                || !Objects.equals(checkIdempotent.getCode(), ResultCode.SUCCESS.getCode())) {
                return checkIdempotent;
            }

            //执行能力业务
            return execute(abilityCmd);
        } finally {
            AbilityContext.clearContext();
        }
    }

    /**
     * 能力点执行前的参数校验
     *
     * @param abilityCmd abilityCmd
     * @return void
     * @author lu_yang
     */
    public abstract void checkHandler(T abilityCmd);

    /**
     * 能力点执行前的幂等校验
     *
     * @param abilityCmd abilityCmd
     * @return com.luyang.framework.protocol.Result
     * @author lu_yang
     */
    public abstract Result<R> checkIdempotent(T abilityCmd);

    /**
     * 执行能力业务
     *
     * @param abilityCmd abilityCmd
     * @return com.luyang.framework.protocol.Result
     * @author lu_yang
     */
    public abstract Result<R> execute(T abilityCmd);
}
